<script>
	import App from './App'
	import http from './common/request';
	import * as msgType from './common/messageType';
	import * as enums from './common/enums';
	import * as wsApi from './common/wssocket';
	import UNI_APP from '@/.env.js'

	export default {
		data() {
			return {
				isInit: false, // 是否完成初始化
				isInBackGroup: false, // 是否在后台运行
				isExit: false, // 是否已退出
				audioTip: null,
				reconnecting: false, // 正在重连标志
				isPushModule: false // 是否勾选了unipush
			}
		},
		methods: {
			init() {
				this.reconnecting = false;
				this.isExit = false;
				// 加载数据
				this.loadStore().then(() => {
					// 初始化websocket
					this.initWebSocket();
					this.reportCid();
					this.initUniPush();
					setTimeout(() => {
						this.$badge.refreshFriendBadge();
						this.$badge.refreshChatBadge();
					}, 1000)
					this.isInit = true;
				}).catch((e) => {
					console.log(e);
					this.exit();
				})
			},
			initWebSocket() {
				let loginInfo = uni.getStorageSync("loginInfo")
				wsApi.connect(UNI_APP.WS_URL, loginInfo.accessToken);
				wsApi.onConnect(() => {
					// 重连成功提示
					if (this.reconnecting) {
						this.onReconnectWs();
					} else {
						// 加载离线消息
						this.pullPrivateOfflineMessage(this.chatStore.privateMsgMaxId);
						this.pullGroupOfflineMessage(this.chatStore.groupMsgMaxId);
						this.pullSystemOfflineMessage(this.chatStore.systemMsgMaxSeqNo);
					}
				});
				wsApi.onMessage((cmd, msgInfo) => {
					if (cmd == 2) {
						// 异地登录，强制下线
						uni.showModal({
							content: '您已在其他地方登录，将被强制下线',
							showCancel: false,
						})
						this.exit();
					} else if (cmd == 3) {
						// 私聊消息
						this.handlePrivateMessage(msgInfo);
					} else if (cmd == 4) {
						// 群聊消息
						this.handleGroupMessage(msgInfo);
					} else if (cmd == 5) {
						// 系统消息
						this.handleSystemMessage(msgInfo);
					}
				});
				wsApi.onClose((res) => {
					console.log("ws断开", res);
					// 重新连接
					this.reconnectWs();

				})
			},
			loadStore() {
				return this.userStore.loadUser().then(() => {
					const promises = [];
					promises.push(this.friendStore.loadFriend());
					promises.push(this.groupStore.loadGroup());
					promises.push(this.chatStore.loadChat());
					promises.push(this.configStore.loadConfig());
					return Promise.all(promises);
				})
			},
			unloadStore() {
				this.friendStore.clear();
				this.groupStore.clear();
				this.chatStore.clear();
				this.userStore.clear();
			},
			pullPrivateOfflineMessage(minId) {
				this.chatStore.setLoadingPrivateMsg(true)
				http({
					url: "/message/private/pullOfflineMessage?minId=" + minId,
					method: 'GET'
				}).catch(() => {
					this.chatStore.setLoadingPrivateMsg(false)
				})
			},
			pullGroupOfflineMessage(minId) {
				this.chatStore.setLoadingGroupMsg(true)
				http({
					url: "/message/group/pullOfflineMessage?minId=" + minId,
					method: 'GET'
				}).catch(() => {
					this.chatStore.setLoadingGroupMsg(false)
				})
			},
			pullSystemOfflineMessage(minSeqNo) {
				this.chatStore.setLoadingSystemMsg(true)
				this.$http({
					url: "/message/system/pullOfflineMessage?minSeqNo=" + minSeqNo,
					method: 'GET'
				}).catch(() => {
					this.chatStore.setLoadingSystemMsg(false)
				})
			},
			handlePrivateMessage(msg) {
				// 标记这条消息是不是自己发的
				msg.selfSend = msg.sendId == this.userStore.userInfo.id;
				// 好友id
				let friendId = msg.selfSend ? msg.recvId : msg.sendId;
				// 会话信息
				let chatInfo = {
					type: 'PRIVATE',
					targetId: friendId
				}
				// 消息加载标志
				if (msg.type == enums.MESSAGE_TYPE.LOADING) {
					this.chatStore.setLoadingPrivateMsg(JSON.parse(msg.content))
					return;
				}
				// 消息已读处理，清空已读数量
				if (msg.type == enums.MESSAGE_TYPE.READED) {
					this.chatStore.resetUnreadCount(chatInfo)
					return;
				}
				// 消息回执处理,改消息状态为已读
				if (msg.type == enums.MESSAGE_TYPE.RECEIPT) {
					this.chatStore.readedMessage({
						friendId: msg.sendId
					})
					return;
				}
				// 消息撤回
				if (msg.type == enums.MESSAGE_TYPE.RECALL) {
					this.chatStore.recallMessage(msg, chatInfo);
					return;
				}
				// 好友申请
				if (msg.type == enums.MESSAGE_TYPE.FRIEND_REQ_APPLY) {
					this.friendStore.addRequest(JSON.parse(msg.content))
					return;
				}
				// 好友申请被同意、拒绝、撤回
				if (msg.type == enums.MESSAGE_TYPE.FRIEND_REQ_APPROVE ||
					msg.type == enums.MESSAGE_TYPE.FRIEND_REQ_REJECT ||
					msg.type == enums.MESSAGE_TYPE.FRIEND_REQ_RECALL) {
					this.friendStore.removeRequest(JSON.parse(msg.content).id)
					return;
				}
				// 新增好友
				if (msg.type == this.$enums.MESSAGE_TYPE.FRIEND_NEW) {
					this.friendStore.addFriend(JSON.parse(msg.content));
					return;
				}
				// 删除好友
				if (msg.type == this.$enums.MESSAGE_TYPE.FRIEND_DEL) {
					this.friendStore.removeFriend(friendId);
					return;
				}
				// 消息插入
				let friend = this.loadFriendInfo(friendId);
				this.insertPrivateMessage(friend, msg);
			},
			insertPrivateMessage(friend, msg) {
				// 单人视频信令
				if (msgType.isRtcPrivate(msg.type)) {
					// #ifdef MP-WEIXIN
					// 小程序不支持音视频
					return;
					// #endif
					// 被呼叫，弹出视频页面
					let delayTime = 100;
					if (msg.type == enums.MESSAGE_TYPE.RTC_SETUP_VOICE ||
						msg.type == enums.MESSAGE_TYPE.RTC_SETUP_VIDEO) {
						let mode = msg.type == enums.MESSAGE_TYPE.RTC_SETUP_VIDEO ? "video" : "voice";
						let pages = getCurrentPages();
						let curPage = pages[pages.length - 1].route;
						if (curPage != "pages/chat/chat-private-video") {
							const friendInfo = encodeURIComponent(JSON.stringify(friend));
							uni.navigateTo({
								url: `/pages/chat/chat-private-video?mode=${mode}&friend=${friendInfo}&isHost=false`
							})
							this.createNotifyMessage(friend.showNickName, msg);
							delayTime = 500;
						}
					}
					setTimeout(() => {
						uni.$emit('WS_RTC_PRIVATE', msg);
					}, delayTime)
					return;
				}
				// 插入消息
				if (msgType.isNormal(msg.type) || msgType.isTip(msg.type) || msgType.isAction(msg.type)) {
					let chatInfo = {
						type: 'PRIVATE',
						targetId: friend.id,
						showName: friend.showNickName,
						headImage: friend.headImage
					};
					// 打开会话
					this.chatStore.openChat(chatInfo);
					// 插入消息
					this.chatStore.insertMessage(msg, chatInfo);
					// 弹出通知栏消息
					this.createNotifyMessage(friend.showNickName, msg);
					// 播放提示音
					this.playAudioTip();
				}
			},
			handleGroupMessage(msg) {
				// 标记这条消息是不是自己发的
				msg.selfSend = msg.sendId == this.userStore.userInfo.id;
				let chatInfo = {
					type: 'GROUP',
					targetId: msg.groupId
				}
				// 消息加载标志
				if (msg.type == enums.MESSAGE_TYPE.LOADING) {
					this.chatStore.setLoadingGroupMsg(JSON.parse(msg.content))
					return;
				}
				// 消息已读处理
				if (msg.type == enums.MESSAGE_TYPE.READED) {
					// 我已读对方的消息，清空已读数量
					this.chatStore.resetUnreadCount(chatInfo)
					return;
				}
				// 消息回执处理
				if (msg.type == enums.MESSAGE_TYPE.RECEIPT) {
					// 更新消息已读人数
					let msgInfo = {
						id: msg.id,
						groupId: msg.groupId,
						readedCount: msg.readedCount,
						receiptOk: msg.receiptOk
					};
					this.chatStore.updateMessage(msgInfo, chatInfo)
					return;
				}
				// 消息撤回
				if (msg.type == enums.MESSAGE_TYPE.RECALL) {
					this.chatStore.recallMessage(msg, chatInfo)
					return;
				}
				// 新增群
				if (msg.type == enums.MESSAGE_TYPE.GROUP_NEW) {
					this.groupStore.addGroup(JSON.parse(msg.content));
					return;
				}
				// 删除群
				if (msg.type == enums.MESSAGE_TYPE.GROUP_DEL) {
					this.groupStore.removeGroup(msg.groupId);
					return;
				}
				// 群消息置顶
				if (msg.type == enums.MESSAGE_TYPE.GROUP_TOP_MESSAGE) {
					let topMessage = msg.content ? JSON.parse(msg.content) : null;
					this.groupStore.updateTopMessage(msg.groupId, topMessage);
					return;
				}
				// 插入消息
				let group = this.loadGroupInfo(msg.groupId);
				this.insertGroupMessage(group, msg);
			},
			insertGroupMessage(group, msg) {
				// 群视频信令
				if (msgType.isRtcGroup(msg.type)) {
					// #ifdef MP-WEIXIN
					// 小程序不支持音视频
					return;
					// #endif
					// 被呼叫，弹出视频页面
					let delayTime = 100;
					if (msg.type == enums.MESSAGE_TYPE.RTC_GROUP_SETUP) {
						let pages = getCurrentPages();
						let curPage = pages[pages.length - 1].route;
						if (curPage != "pages/chat/chat-group-video") {
							const userInfos = encodeURIComponent(msg.content);
							const inviterId = msg.sendId;
							const groupId = msg.groupId;
							const url = `/pages/chat/chat-group-video?groupId=${groupId}&isHost=false
												&inviterId=${inviterId}&userInfos=${userInfos}`;
							uni.navigateTo({ url: url })
							this.createNotifyMessage(group.showGroupName, msg);
							delayTime = 500;
						}
					}
					// 消息转发到chat-group-video页面进行处理
					setTimeout(() => {
						uni.$emit('WS_RTC_GROUP', msg);
					}, delayTime)
					return;
				}
				// 插入消息
				if (msgType.isNormal(msg.type) || msgType.isTip(msg.type) || msgType.isAction(msg.type)) {
					let chatInfo = {
						type: 'GROUP',
						targetId: group.id,
						showName: group.showGroupName,
						headImage: group.headImageThumb
					};
					// 打开会话
					this.chatStore.openChat(chatInfo);
					// 插入消息
					this.chatStore.insertMessage(msg, chatInfo);
					// 弹出通知栏消息
					this.createNotifyMessage(group.showGroupName, msg);
					// 播放提示音
					this.playAudioTip();
				}
			},
			handleSystemMessage(msg) {
				// 消息加载标志
				if (msg.type == this.$enums.MESSAGE_TYPE.LOADING) {
					this.chatStore.setLoadingSystemMsg(JSON.parse(msg.content));
					return;
				}
				// 消息已读处理 
				if (msg.type == enums.MESSAGE_TYPE.READED) {
					// 我已读对方的消息，清空已读数量
					let chatInfo = {
						type: 'SYSTEM',
						targetId: 0
					}
					this.chatStore.resetUnreadCount(chatInfo)
					return;
				}
				if (msg.type == enums.MESSAGE_TYPE.USER_BANNED) {
					// 用户被封禁
					wsApi.close(3099);
					uni.showModal({
						content: '您的账号已被管理员封禁，原因:' + msg.content,
						showCancel: false,
					})
					this.exit();
					return;
				}
				if (msg.type == enums.MESSAGE_TYPE.USER_UNREG) {
					// 用户账号已注销
					wsApi.close(3099);
					uni.showModal({
						content: '您的账号已注销',
						showCancel: false,
					})
					this.exit();
					return;
				}
				// 插入消息
				this.insertSystemMessage(msg);
			},
			insertSystemMessage(msg) {
				let headImage = '/static/image/chat_system.png';
				let chatInfo = {
					type: 'SYSTEM',
					targetId: 0,
					showName: "系统通知",
					headImage: headImage
				};
				// 打开会话
				this.chatStore.openChat(chatInfo);
				// 插入消息
				this.chatStore.insertMessage(msg, chatInfo);
			},
			loadFriendInfo(id, callback) {
				let friend = this.friendStore.findFriend(id);
				if (!friend) {
					friend = {
						id: id,
						showNickName: "未知用户",
						headImage: ""
					}
				}
				return friend;
			},
			loadGroupInfo(id) {
				let group = this.groupStore.findGroup(id);
				if (!group) {
					group = {
						id: id,
						showGroupName: "未知群聊",
						headImageThumb: ""
					}
				}
				return group;
			},
			exit() {
				console.log("exit");
				this.isExit = true;
				wsApi.close(3099);
				uni.removeStorageSync("loginInfo");
				uni.reLaunch({
					url: "/pages/login/login"
				})
				this.unloadStore();
			},
			playAudioTip() {
				// 音频播放无法成功
				// this.audioTip = uni.createInnerAudioContext();
				// this.audioTip.src =  "/static/audio/tip.wav";
				// this.audioTip.play();
			},
			refreshToken(loginInfo) {
				return new Promise((resolve, reject) => {
					if (!loginInfo || !loginInfo.refreshToken) {
						reject();
						return;
					}
					http({
						url: '/refreshToken',
						method: 'PUT',
						header: {
							refreshToken: loginInfo.refreshToken
						}
					}).then((newLoginInfo) => {
						uni.setStorageSync("loginInfo", newLoginInfo)
						resolve()
					}).catch((e) => {
						reject(e)
					})
				})
			},
			reconnectWs() {
				// 已退出则不再重连
				if (this.isExit) {
					return;
				}
				// 记录标志
				this.reconnecting = true;
				// 重新加载一次个人信息，目的是为了保证网络已经正常且token有效
				this.userStore.loadUser().then((userInfo) => {
					uni.showToast({
						title: '连接已断开，尝试重新连接...',
						icon: 'none'
					})
					// 重新连接
					let loginInfo = uni.getStorageSync("loginInfo")
					wsApi.reconnect(UNI_APP.WS_URL, loginInfo.accessToken);
				}).catch(() => {
					// 5s后重试
					setTimeout(() => {
						this.reconnectWs();
					}, 5000)
				})
			},
			onReconnectWs() {
				this.reconnecting = false;
				// 重新加载好友和群聊
				const promises = [];
				promises.push(this.friendStore.loadFriend());
				promises.push(this.groupStore.loadGroup());
				Promise.all(promises).then(() => {
					uni.showToast({
						title: "已重新连接",
						icon: 'none'
					})
					// 加载离线消息
					this.pullPrivateOfflineMessage(this.chatStore.privateMsgMaxId);
					this.pullGroupOfflineMessage(this.chatStore.groupMsgMaxId);
					this.pullSystemOfflineMessage(this.chatStore.systemMsgMaxSeqNo);
					// 更新角标
					this.$badge.refreshFriendBadge();
					this.$badge.refreshChatBadge();
				}).catch((e) => {
					console.log(e);
					this.exit();
				})
			},
			createNotifyMessage(title, msg) {
				if (!this.isPushModule) {
					return
				}
				const content = this.createNotifyContent(msg)
				// 仅在后台时弹出提示
				if (!content || !this.isInBackGroup) {
					return;
				}
				const options = {
					cover: true,
					sound: 'system',
					title: title,
					//icon: 'static/tarbar/chat_active.png'
				};
				plus.push.createMessage(content, {}, options);
			},
			createNotifyContent(msg) {
				let content = msg.content;
				switch (msg.type) {
					case enums.MESSAGE_TYPE.IMAGE:
						content = "[图片]";
						break;
					case enums.MESSAGE_TYPE.VIDEO:
						content = "[视频]";
						break;
					case enums.MESSAGE_TYPE.FILE:
						content = "[文件]";
						break;
					case enums.MESSAGE_TYPE.AUDIO:
						content = "[语音]";
						break;
					case enums.MESSAGE_TYPE.RTC_SETUP_VOICE:
					case enums.MESSAGE_TYPE.RTC_SETUP_VOICE:
						content = "邀请您进行通话";
						break;
					case enums.MESSAGE_TYPE.RTC_GROUP_SETUP:
						content = "邀请您加入通话";
						break;
				}
				return content;
			},
			initUniPush() {
				if (!this.isPushModule) {
					return
				}
				plus.push.setAutoNotification(true);
				plus.push.clear();
				const clientInfo = plus.push.getClientInfo();
				plus.push.addEventListener('click', (message) => {
					const msgInfo = message.payload;
					this.onClickNotifyMessage(msgInfo);
				});
			},
			onClickNotifyMessage(msgInfo) {
				if (msgInfo.type == enums.MESSAGE_TYPE.RTC_GROUP_SETUP) {
					this.$http({
						url: "/webrtc/group/info?groupId=" + msgInfo.groupId,
						method: 'GET'
					}).then((rtcInfo) => {
						if (!rtcInfo.isChating) {
							return uni.showToast({
								title: '通话已结束',
								icon: 'none'
							})
						}
						// 进入被呼叫页面
						msgInfo.content = JSON.stringify(rtcInfo.userInfos)
						setTimeout(() => this.handleGroupMessage(msgInfo), 500)
					})
				} else if (msgInfo.type == enums.MESSAGE_TYPE.RTC_SETUP_VIDEO ||
					msgInfo.type == enums.MESSAGE_TYPE.RTC_SETUP_VOICE) {
					this.$http({
						url: "/webrtc/private/info?uid=" + msgInfo.sendId,
						method: 'GET'
					}).then((rtcInfo) => {
						if (!rtcInfo.isChating) {
							return uni.showToast({
								title: '通话已结束',
								icon: 'none'
							})
						}
						// 进入被呼叫页面
						setTimeout(() => this.handlePrivateMessage(msgInfo), 500)
					})
				} else if (msgInfo.type == enums.MESSAGE_TYPE.FRIEND_REQ_APPLY) {
					// 好友验证
					this.onFriendRequestApplyNotify(msgInfo);
				}
			},
			onFriendRequestApplyNotify(msgInfo) {
				if (!this.isInit) {
					// 等待初始化完成再处理
					setTimeout(() => this.onFriendRequestApplyNotify(msgInfo), 1000);
					return;
				}
				// 跳转到验证页面
				let request = JSON.parse(msgInfo.content);
				if (!this.friendStore.isInSendRequest(request.sendId)) {
					uni.showToast({
						title: "该请求已被处理或撤销",
						icon: 'none'
					})
					return;
				}
				uni.navigateTo({
					url: `/pages/common/user-info?id=${request.sendId}&requestId=${request.id}`
				})
			},
			reportCid() {
				// APP需要上报cid，用于离线推送
				if (!this.isPushModule) {
					return
				}
				const clientInfo = plus.push.getClientInfo();
				const cid = clientInfo.clientid;
				if (cid && cid != "null") {
					console.log("cid:", cid)
					// 上报cid
					http({
						url: '/user/reportCid?cid=' + cid,
						method: 'POST'
					})
				} else {
					// 有时cid会拿不到,1s后重试
					setTimeout(() => this.reportCid(), 1000);
				}
			},
			removeCid() {
				if (!this.isPushModule) {
					return
				}
				http({
					url: '/user/removeCid',
					method: 'DELETE'
				})
			},
			closeSplashscreen(delay) {
				// #ifdef APP-PLUS
				// 关闭开机动画
				setTimeout(() => {
					plus.navigator.closeSplashscreen()
				}, delay)
				// #endif
			},
			checkPushModule() {
				// #ifdef APP-PLUS
				if (plus && plus.push) {
					plus.runtime.getProperty(plus.runtime.appid, (info) => {
						this.isPushModule = info.features.includes('push') || info.features.includes('Push');
					})
				}
				// #endif
			}
		},
		onLaunch() {
			this.$mountStore();
			// 检测是否打包了unipush模块
			this.checkPushModule();
			// 延迟1s，避免用户看到页面跳转
			this.closeSplashscreen(1000);
			// 加载系统配置
			this.configStore.loadConfig();
			// 登录状态校验
			let loginInfo = uni.getStorageSync("loginInfo")
			this.refreshToken(loginInfo).then(() => {
				console.log("token刷新成功")
				// #ifdef H5
				// 跳转到聊天页
				// uni.navigateTo({
				// 	url: "/pages/chat/chat"
				// })
				// #endif
				// 初始化
				this.init();
				this.closeSplashscreen(0);
			}).catch(() => {
				console.log("token刷新失败")
				// 跳转到登录页
				uni.navigateTo({
					url: "/pages/login/login"
				})
			})
		},
		onShow() {
			this.isInBackGroup = false;
			if (this.isPushModule) {
				plus.push.clear();
			}
		},
		onHide() {
			this.isInBackGroup = true;
		}
	}
</script>

<style lang="scss">
	@import "@/uni_modules/uview-plus/index.scss";
	@import "@/im.scss";
	@import url('./static/icon/iconfont.css');

	// #ifdef H5 
	uni-page-head {
		display: none; // h5浏览器本身就有标题
	}

	// #endif

	.tab-page {
		display: flex;
		flex-direction: column;
		color: $im-text-color;
		font-size: $im-font-size;
		font-family: $font-family;
	}


	.page {
		position: relative;
		// #ifdef H5
		height: calc(100vh); // app平台还要减去顶部手机状态栏高度
		top: $im-nav-bar-height;
		// #endif
		// #ifndef H5
		height: calc(100vh - var(--status-bar-height)); // app平台还要减去顶部手机状态栏高度
		top: calc($im-nav-bar-height + var(--status-bar-height));
		// #endif
		color: $im-text-color;
		background-color: $im-bg;
		font-size: $im-font-size;
		font-family: $font-family;
	}


	view,
	scroll-view,
	swiper,
	swiper-item,
	cover-view,
	cover-image,
	icon,
	text,
	rich-text,
	progress,
	button,
	checkbox,
	form,
	input,
	label,
	radio,
	slider,
	switch,
	textarea,
	navigator,
	audio,
	camera,
	image,
	video {
		box-sizing: border-box;
	}

	image {
		display: block;
	}
</style>